#include <algorithm/analytical_model/algorithm/cuda/evaluation/metrics/RAD.cuh>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/utils/executor/AsyncFunctionExecutor.h>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/utils/executor/async/MetricsRADExecutor.h>

#include <boost/pfr.hpp>

#include <bit>

using namespace solar::cuda;

namespace solar::cuda::async::internal
{
    struct MetricsRADArgs1
    {
            float* d_input_;
            float* d_ground_truth_;
            inter_op::Int2 resolution_;
            cudaStream_t stream_;
    };
} // namespace solar::cuda::async::internal

void async::MetricsRADExecutor::execute(FunctionArgs* args)
{
    auto* rad_args = std::bit_cast<async::internal::MetricsRADArgs1*>(args);
    this->future_ =
        std::apply(solar::cuda::metrics::async::RAD, boost::pfr::structure_to_tuple(*rad_args));
}

auto async::MetricsRADExecutor::getResult() -> std::any
{
    return std::get<0>(this->future_).get() / std::get<1>(this->future_).get();
}

void async::MetricsRADExecutor::wait()
{
    std::get<0>(this->future_).get();
    std::get<1>(this->future_).get();
}
